package com.anton46.collectionitempicker;

import ohos.agp.animation.Animator;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.*;
import ohos.agp.components.element.Element;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.components.element.StateElement;
import ohos.agp.render.Paint;
import ohos.agp.utils.LayoutAlignment;
import ohos.app.Context;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import static com.anton46.collectionitempicker.AttrUtils.*;

public class CollectionPicker extends DirectionalLayout implements Component.LayoutRefreshedListener, ComponentContainer.ArrangeListener {

    public static final int LAYOUT_WIDTH_OFFSET = 3;

    private LayoutScatter mInflater;

    private List<Item> mItems = new ArrayList<>();
    private DirectionalLayout mRow;
    private HashMap<String, Object> mCheckedItems = new HashMap<>();
    private OnItemClickListener mClickListener;
    private int mWidth;
    private int mItemMargin = 10;
    private int textPaddingLeft = 8;
    private int textPaddingRight = 8;
    private int textPaddingTop = 5;
    private int texPaddingBottom = 5;
    private int mAddIcon ;
    private int mCancelIcon ;
    private int mLayoutBackgroundColorNormal = ResourceTable.Color_blue;
    private int mLayoutBackgroundColorPressed = ResourceTable.Color_red;
    private int mTextColor = ResourceTable.Color_white;
    private int mRadius = 10;
    private boolean mInitialized;

    private boolean simplifiedTags;


    public CollectionPicker(Context context) {
        this(context, null);
    }

    public CollectionPicker(Context context, AttrSet attrs) {
        this(context, attrs, null);
    }


    public CollectionPicker(Context context, AttrSet attrs, String defStyle) {
        super(context, attrs, defStyle);
        mInflater = LayoutScatter.getInstance(context);

        mItemMargin = AttrUtils.getDimensionFromAttr(attrs, CP_ITEM_MARGIN, Utils.vpToPx(this.getContext(), mItemMargin));
        textPaddingLeft = AttrUtils.getDimensionFromAttr(attrs, CP_TEXT_PADDING_LEFT, Utils.vpToPx(this.getContext(), textPaddingLeft));
        textPaddingRight = AttrUtils.getDimensionFromAttr(attrs, CP_TEXT_PADDING_RIGHT, Utils.vpToPx(this.getContext(), textPaddingRight));
        textPaddingTop = AttrUtils.getDimensionFromAttr(attrs, CP_TEXT_PADDING_TOP, Utils.vpToPx(this.getContext(), textPaddingTop));
        texPaddingBottom = AttrUtils.getDimensionFromAttr(attrs, CP_TEXT_PADDING_BOTTOM, Utils.vpToPx(this.getContext(), texPaddingBottom));
        mAddIcon = AttrUtils.getMediaFromAttr(attrs, CP_ADD_ICON, ResourceTable.Media_ic_menu_add);
        mCancelIcon = AttrUtils.getMediaFromAttr(attrs, CP_CANCEL_ICON, ResourceTable.Media_ic_menu_close_clear_cancel);
        mLayoutBackgroundColorNormal = AttrUtils.getColorFromAttr(attrs, CP_ITEM_BACKGROUND_NORMAL, mLayoutBackgroundColorNormal);
        mLayoutBackgroundColorPressed = AttrUtils.getColorFromAttr(attrs, CP_ITEM_BACKGROUND_PRESSED, mLayoutBackgroundColorPressed);
        mRadius = AttrUtils.getDimensionFromAttr(attrs, CP_ITEM_RADIUS, mRadius);
        mTextColor = AttrUtils.getColorFromAttr(attrs, CP_ITEM_TEXT_COLOR, mTextColor);
        simplifiedTags = AttrUtils.getBooleanFromAttr(attrs, CP_SIMPLIFIED, false);

        setOrientation(VERTICAL);
        setAlignment(LayoutAlignment.HORIZONTAL_CENTER);

        setLayoutRefreshedListener(this);
        setArrangeListener(this);
    }

    @Override
    public boolean onArrange(int l, int t, int w, int h) {
        mWidth = w;
        return false;
    }
    @Override
    public void onRefreshed(Component component) {
        if (!mInitialized) {
            mInitialized = true;
            drawItemView();
        }
    }

    /**
     * Selected flags
     */
    public void setCheckedItems(HashMap<String, Object> checkedItems) {
        mCheckedItems = checkedItems;
    }

    public HashMap<String, Object> getCheckedItems() {
        return mCheckedItems;
    }

    public void drawItemView() {
        if (!mInitialized) {
            return;
        }

        clearUi();

        float totalPadding = getPaddingLeft() + getPaddingRight();
        int indexFrontView = 0;

        LayoutConfig itemParams = getItemLayoutParams();

        for (int i = 0; i < mItems.size(); i++) {
            final Item item = mItems.get(i);
            if (mCheckedItems != null && mCheckedItems.containsKey(item.id)) {
                item.isSelected = true;
            }

            final int position = i;
            final Component itemLayout = createItemView(item);

            if (!simplifiedTags) {
                itemLayout.setClickedListener(new ClickedListener() {
                    @Override
                    public void onClick(Component component) {
                        animateView(component);
                        item.isSelected = !item.isSelected;
                        if (item.isSelected) {
                            mCheckedItems.put(item.id, item);
                        } else {
                            mCheckedItems.remove(item.id);
                        }
                        itemLayout.setBackground(getSelector(item));

                        Image iconView = (Image) itemLayout.findComponentById(ResourceTable.Id_item_icon);
                        iconView.setPixelMap(getItemIcon(item.isSelected));
                        if (mClickListener != null) {
                            mClickListener.onClick(item, position);
                        }
                    }
                });
            }

            Text itemTextView = (Text) itemLayout.findComponentById(ResourceTable.Id_item_name);
            itemTextView.setText(item.text);
            itemTextView.setPadding(textPaddingLeft, textPaddingTop, textPaddingRight,
                    texPaddingBottom);
            itemTextView.setTextColor(ResUtil.getNewColor(mContext, mTextColor));



            float itemWidth = new Paint().getTextBounds(itemTextView.getText()).getWidth() + textPaddingLeft
                    + textPaddingRight;

            // if (!simplifiedTags) {
            Image indicatorView = (Image) itemLayout.findComponentById(ResourceTable.Id_item_icon);
            indicatorView.setPixelMap(getItemIcon(item.isSelected));
            indicatorView.setPadding(0, textPaddingTop, textPaddingRight, texPaddingBottom);

            if (simplifiedTags) {
                indicatorView.setVisibility(HIDE);
            }

            itemWidth += Utils.vpToPx(getContext(), 30) + textPaddingLeft
                    + textPaddingRight;

            if (mWidth <= totalPadding + itemWidth + Utils
                    .vpToPx(this.getContext(), LAYOUT_WIDTH_OFFSET)) {
                totalPadding = getPaddingLeft() + getPaddingRight();
                indexFrontView = i;
                addItemView(itemLayout, itemParams, true, i);
            } else {
                if (i != indexFrontView) {
                    itemParams.setMarginLeft(mItemMargin);
                    totalPadding += mItemMargin;
                }
                addItemView(itemLayout, itemParams, false, i);
            }
            totalPadding += itemWidth;
        }
        // }
    }

    private Component createItemView(Item item) {
        Component view = mInflater.parse(ResourceTable.Layout_item_layout, this, false);
        view.setBackground(getSelector(item));
        return view;
    }

    private LayoutConfig getItemLayoutParams() {
        LayoutConfig itemParams = new LayoutConfig(
                ComponentContainer.LayoutConfig.MATCH_CONTENT,
                ComponentContainer.LayoutConfig.MATCH_CONTENT);
        itemParams.setMarginsTopAndBottom(mItemMargin / 2, mItemMargin / 2);

        return itemParams;
    }

    private int getItemIcon(Boolean isSelected) {
        return isSelected ? mCancelIcon : mAddIcon;
    }

    private void clearUi() {
        removeAllComponents();
        mRow = null;
    }

    private void addItemView(Component itemView, ComponentContainer.LayoutConfig chipParams, boolean newLine,
                             int position) {
        if (mRow == null || newLine) {
            mRow = new DirectionalLayout(getContext());
            mRow.setAlignment(LayoutAlignment.CENTER);
            mRow.setOrientation(HORIZONTAL);

            LayoutConfig params = new LayoutConfig(
                    ComponentContainer.LayoutConfig.MATCH_PARENT,
                    ComponentContainer.LayoutConfig.MATCH_CONTENT);

            mRow.setLayoutConfig(params);

            addComponent(mRow);
        }

        mRow.addComponent(itemView, chipParams);
        animateItemView(itemView, position);
    }

    private Element getSelector(Item item) {
        return item.isSelected ? getSelectorSelected() : getSelectorNormal();
    }

    private StateElement getSelectorNormal() {
        StateElement states = new StateElement();

        ShapeElement gradientDrawable = new ShapeElement();
        gradientDrawable.setRgbColor(RgbColor.fromArgbInt(mLayoutBackgroundColorPressed));
        gradientDrawable.setCornerRadius(mRadius);

        states.addState(new int[]{ComponentState.COMPONENT_STATE_PRESSED}, gradientDrawable);

        gradientDrawable = new ShapeElement();
        gradientDrawable.setRgbColor(RgbColor.fromArgbInt(mLayoutBackgroundColorNormal));
        gradientDrawable.setCornerRadius(mRadius);

        states.addState(new int[]{ComponentState.COMPONENT_STATE_EMPTY}, gradientDrawable);

        return states;
    }

    private StateElement getSelectorSelected() {
        StateElement states = new StateElement();
        ShapeElement gradientDrawable = new ShapeElement();
        gradientDrawable.setRgbColor(RgbColor.fromArgbInt(mLayoutBackgroundColorNormal));
        gradientDrawable.setCornerRadius(mRadius);

        states.addState(new int[]{ComponentState.COMPONENT_STATE_PRESSED}, gradientDrawable);

        gradientDrawable = new ShapeElement();
        gradientDrawable.setRgbColor(RgbColor.fromArgbInt(mLayoutBackgroundColorPressed));
        gradientDrawable.setCornerRadius(mRadius);

        states.addState(new int[]{ComponentState.COMPONENT_STATE_EMPTY}, gradientDrawable);

        return states;
    }

    public List<Item> getItems() {
        return mItems;
    }

    public void setItems(List<Item> items) {
        mItems = items;
    }

    public void clearItems() {
        mItems.clear();
    }

    public void setOnItemClickListener(OnItemClickListener clickListener) {
        mClickListener = clickListener;
    }

    private void animateView(final Component view) {
        view.setScaleY(1f);
        view.setScaleX(1f);

        view.createAnimatorProperty()
                .scaleX(1.2f)
                .scaleY(1.2f)
                .setDuration(100)
                .setDelay(0)
                .setCurveType(Animator.CurveType.DECELERATE)
                .setStateChangedListener(new Animator.StateChangedListener() {
                    @Override
                    public void onStart(Animator animator) {

                    }

                    @Override
                    public void onStop(Animator animator) {

                    }

                    @Override
                    public void onCancel(Animator animator) {

                    }

                    @Override
                    public void onEnd(Animator animator) {
                        reverseAnimation(view);
                    }

                    @Override
                    public void onPause(Animator animator) {

                    }

                    @Override
                    public void onResume(Animator animator) {

                    }
                })
                .start();
    }

    private void reverseAnimation(Component view) {
        view.setScaleY(1.2f);
        view.setScaleX(1.2f);

        view.createAnimatorProperty()
                .scaleX(1f)
                .scaleY(1f)
                .setDuration(100)
                .setStateChangedListener(null)
                .start();
    }

    private void animateItemView(Component view, int position) {
        long animationDelay = 600;

        animationDelay += position * 30;

        view.setScaleY(0);
        view.setScaleX(0);
        view.createAnimatorProperty()
                .scaleY(1)
                .scaleX(1)
                .setDuration(200)
                .setCurveType(Animator.CurveType.DECELERATE)
                .setStateChangedListener(null)
                .setDelay(animationDelay)
                .start();
    }



}
